const fs = require("fs"); // 系统模块 无需安装
const path = require("path"); // 系统模块 无需安装
const { addLog, promiseLog,copyDir } = require("../utils");
const { exec } = require('child_process');
const {app_assets,basePath,createObj, pathType,moduleConfig} = require('../config')
const {android,androidJava} = require("../template");
const {copySdk} = require("./sdk");

const JSON5 = require("json5");
let templates = {}
let proPath = ''
//Android
function androidChangeFile({ projectName ,projectPath},manifestFile) {
  proPath = projectPath || path.join(__dirname, "../project", projectName);
  return promiseLog({ text: "移动文件到对应目录", projectName }, () => {
    return new Promise((resolve, reject) => {
      let projectPath = path.resolve(proPath,'dist/build/app-plus');
      // let manifestFile = JSON5.parse(fs.readFileSync(proPath, "src/manifest.json"), "utf-8"));
      let sdkDir =  fs.readdirSync(path.resolve(basePath,'baseAndroidSDK')).filter(item=>item != '.DS_Store')
      // 数组里面取Android开头的目录
      sdkDir = sdkDir.filter(item=>{
        return item.indexOf('Android') != -1
      })[0]
      let outBuildPath = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS',app_assets.path)
      const {appid} = manifestFile
      try {
        fs.rmSync(outBuildPath, { recursive: true, force: true });     
        addLog(`删除旧项目成功,开始创建目录`+ path.resolve(outBuildPath,appid,'www'),projectName)
        // 创建文件夹
        fs.mkdirSync(path.resolve(outBuildPath,appid,'www'), { recursive: true });
        addLog(`创建目录成功`,projectName)
        // 复制文件
        copyDir(projectPath,path.resolve(outBuildPath,appid,'www')).then(()=>{
          resolve()
        }).catch(err=>{
          addLog(`复制到对应目录失败`,projectName)
          reject(err)
        })
      }catch(err){
        addLog(`移动文件到对应目录失败`,projectName)
        reject(err)
      }
     
    });
  });
}

function androidSign({ projectName, },projectData) {
  // 由于appkey 必须和控制台一直所以需在https://nativesupport.dcloud.net.cn/AppDocs/usesdk/appkey.html# 申请自己生成无法打包
  return Promise.resolve()
}
// 模块处理
function androidAddMode({ projectName },manifestFile,projectData) {
    return new Promise((resolve, reject) => {
      let modules = Object.keys( manifestFile['app-plus'].modules)
      let sdkConfig = manifestFile['app-plus'].distribute.sdkConfigs
      if(sdkConfig.ad && Object.keys(sdkConfig.ad).length > 0){
        modules.push('AD')
      }
      addLog("模块列表"+JSON.stringify( modules ), projectName )
      // 处理sdkConfig
      changeModels(sdkConfig,moduleConfig(),modules,projectName,projectData).then(resolve).catch(reject)
    });
}
// 移动文件生成模块配置等
function changeModels(sdkConfig,moduleConfig,modules,projectName,projectData){
  return new Promise((resolve,reject) => {
    const javaData = androidJava(projectData)

    let len = 0
    let sdkDir =  fs.readdirSync(path.resolve(basePath,'baseAndroidSDK')).filter(item=>item != '.DS_Store')
    sdkDir = sdkDir.filter(item=>{
      return item.indexOf('Android') != -1
    })[0]
    let iconDir = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS/simpleDemo/src/main/res/drawable')
    let projectPath = path.resolve(proPath);
    
    modules.forEach(async key=>{
      addLog("正在处理模块--"+key, projectName)
      // 单独处理实人认证
      if(key == 'FacialRecognitionVerify'){
        if(!sdkConfig[moduleConfig[key].sdkKey]) {
          return reject('检测到有实人认证模块，需要手动去项目的manifest.json 源码视图 app-plus => distribute => sdkConfigs 下面添加"facialRecognitionVerify":{"ver":true},')
        } 
      }
      if(key == 'Webview-x5'){
        if(!sdkConfig[moduleConfig[key].sdkKey]) {
          return reject('检测到使用x5内核，需要手动去项目的manifest.json 源码视图 app-plus => distribute => sdkConfigs 下面添加"webx5":{"ver":true},')
        } 
      }
      if(moduleConfig[key].sdkFile){ 
        if(moduleConfig[key].sdkKey == 'push'){
          sdkConfig.push = {...sdkConfig.push.unipush}
           // moduleConfig[key].sdkFile.outFile
           for(let key3 in sdkConfig[moduleConfig[key].sdkKey]){
             if(key3 == 'icons'){
               Object.keys( sdkConfig[moduleConfig[key].sdkKey].icons.small).some(key4=>{
                 if(sdkConfig[moduleConfig[key].sdkKey].icons.small[key4]){
                   copySdk(path.resolve(projectPath,sdkConfig[moduleConfig[key].sdkKey].icons.small[key4]),path.resolve(iconDir,'push_icon.png')).catch(reject)
                   return true
                 }
               })
             }
           }
        }
      

        // moduleConfig[key].sdkFile
        for(let key2 in moduleConfig[key].sdkFile){
          switch (key2) {
            case 'file':
              if(moduleConfig[key].sdkFile.file.default){
                for(let i=0;i<moduleConfig[key].sdkFile.file.default.length;i++){
                  let file = moduleConfig[key].sdkFile.file.default[i]
                  await copyModuleAar(file)
                  addLog("模块--"+key+'文件'+file+'复制成功', projectName)
                }
              }
              for(let key3 in sdkConfig[moduleConfig[key].sdkKey]){
                if(moduleConfig[key].sdkFile.file[key3]){
                  for(let i=0;i<moduleConfig[key].sdkFile.file[key3].length;i++){
                    let file = moduleConfig[key].sdkFile.file[key3][i]
                    await copyModuleAar(file)
                    addLog("模块--"+key+'文件'+file+'复制成功', projectName)
                  }
                }  
              }
              break;
            case 'dependencies':
              for(let key3 in moduleConfig[key].sdkFile.dependencies){
                console.log('key3',key3,sdkConfig[moduleConfig[key].sdkKey])
                if(sdkConfig[moduleConfig[key].sdkKey][key3]){
                  sdkConfig[moduleConfig[key].sdkKey][key3]['dependencies'] = moduleConfig[key].sdkFile.dependencies[key3]
                }
              }
              break;
            case 'configName':
              // 判断是否有配置文件
              if(!fs.existsSync(path.resolve(projectPath,'moduleConfig.json'))){
                return reject('模块配置文件不存在')
              }
              if(!JSON5.parse( fs.readFileSync(path.resolve(projectPath,'moduleConfig.json'),'utf-8'))[moduleConfig[key].sdkFile.configName]){
                return reject(moduleConfig[key].sdkFile.configName+'配置不存在')
              }
              let modelOption = JSON5.parse(fs.readFileSync(path.resolve(projectPath,'moduleConfig.json'),'utf-8'))
              sdkConfig[moduleConfig[key].sdkFile.configName] = modelOption[moduleConfig[key].sdkFile.configName]
              break;
            case 'outFile':
              for(let key3 in sdkConfig[moduleConfig[key].sdkKey]){
                if(moduleConfig[key].sdkFile.outFile[key3]){
                  let servicesFile = path.resolve(projectPath,moduleConfig[key].sdkFile.outFile[key3])
                  let outPath = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS/simpleDemo/')
                  await copySdk(servicesFile,path.resolve(outPath,moduleConfig[key].sdkFile.outFile[key3]))
                }
              }
              break;
            case "javaFile": 
              for(const key3 in sdkConfig[moduleConfig[key].sdkKey]){
                if(!moduleConfig[key].sdkFile.javaFile[key3]) continue
                // 判断java目录下面是否有目录 没有就创建目录
                let javaPath = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS/simpleDemo/src/main/java',projectData.packageName.replace(/\./g,'/'))
                if(!fs.existsSync(javaPath)){
                  fs.mkdirSync(javaPath, { recursive: true });
                }
                moduleConfig[key].sdkFile.javaFile[key3].forEach(item=>{
                  let javaFile = path.resolve(javaPath,item+'.java')
                  let configData = javaData[item]
                  fs.writeFileSync(javaFile,configData,'utf-8')
                })
              }
              break; 
          }
        }
        len++
      }else{
        len++
      }
      addLog("模块--"+key+'处理完成', projectName)
    })
    let tTime = setInterval(()=>{
      if(len == modules.length){
        clearInterval(tTime)
        tTime = null
        let pushSdk = {}
        for(let key1 in sdkConfig){
            for(let key in moduleConfig){
              if((modules.includes(key) && moduleConfig[key].sdkKey == key1) || key1.indexOf('UserConfig') != -1 ){
                pushSdk[key1] = sdkConfig[key1]
              }
            }
        }
        resolve(pushSdk)
      }
    },60)
  })
}

function copyModuleAar(file){
  let sdkDir =  fs.readdirSync(path.resolve(basePath,'baseAndroidSDK')).filter(item=>item != '.DS_Store')
  sdkDir = sdkDir.filter(item=>{
    return item.indexOf('Android') != -1
  })[0]
  let baseLibDir =path.resolve(basePath,'baseAndroidSDK',sdkDir,'SDK/libs')
  let outLibDir = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS/simpleDemo/libs')
  return new Promise(async (resolve)=>{
    if(file.indexOf('*') != -1){
      // *. 的意思是版本号 例如 3.2.0. 处理*. 
      let preName = file.split('*')[0]
      let fileType = file.split('*')[1]
      let reg = new RegExp(preName+'\\d([\\s\\S]*)'+fileType,'mg'); 
      // 获取目录下的文件
      let files = fs.readdirSync(path.resolve(baseLibDir)).filter(item=>item != '.DS_Store')
      // 如果符合规则 就覆盖file
      for(let i=0;i<files.length;i++){
        if(reg.test(files[i])){
          file = files[i]
          break
        }
      }
    }
    console.log('file',file)
    await copySdk(path.resolve(baseLibDir,file),path.resolve(outLibDir,file))
    resolve()
  })
}


// 获取权限
function getPermission(manifestFile) {
  return new Promise((resolve, reject) => {
    try{
      resolve(manifestFile['app-plus'].distribute.android.permissions)
    }catch(err){
      reject('权限获取失败')
    }
  });
}
// 获取logo
function getLogo(manifestFile) {
  return new Promise((resolve, reject) => {
    try{
      resolve( manifestFile['app-plus'].distribute.icons.android.xxxhdpi)
    }catch(err){
      reject('logo获取失败----需要先在编译器选择logo后进行打包')
    }
  });
}
// 获取启动图
function getSplashscreen(manifestFile) {
  return new Promise((resolve, reject) => {
    try{
      let app_start_img = ''
      for(let key in manifestFile['app-plus'].distribute.splashscreen.android){
        if(key){
          app_start_img = manifestFile['app-plus'].distribute.splashscreen.android[key]
          break
        }
      }
      resolve(app_start_img) 
    }catch(err){
      resolve('')
    }
  });
}

 function outAndroid( projectName,manifestFile,projectData ) {
  proPath = projectData.projectPath || path.join(__dirname, "../project", projectName);
  let sdkDir =  fs.readdirSync(path.resolve(basePath,'baseAndroidSDK')).filter(item=>item != '.DS_Store')
  sdkDir = sdkDir.filter(item=>{
    return item.indexOf('Android') != -1
  })[0]
  console.log('开始生成打包文件')

  return promiseLog({ text: "生成打包文件", projectName }, () => {
    return new Promise((resolve, reject) => {
      tempTofile(projectName,manifestFile,projectData,sdkDir).then(()=>{
        console.log('当前运行环境',process.platform)
        let runExec = 'gradle assembleRelease'
        if(global.process.platform === "win32"){
          runExec = 'gradlew assembleRelease'
        }
        // 执行打包方法
        exec('cd '+ path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS') + ' && '+runExec,function(err, stdout, stderr){
          if(err){
            console.log('打包失败',err)
            addLog('安卓构建失败---'+err,projectName)
            reject('打包失败'+err)
          }else{
            resolve()
            console.log('打包成功',stdout)
          }
        })
      }).catch(err=>{
        reject(err)
        addLog('tempTofile失败'+err,projectName)
      })
    });
  });
}

// 这些是需要同步执行的打包流程
// 应用名称 strings.xml
// 应用图标 drawable
// 应用启动图
// 应用build.gradle
// 应用AndroidManifest
// 应用方向

function getPageOrientation(projectName){
  return new Promise((resolve, reject) => {
    try{
      let data = JSON5.parse(fs.readFileSync(path.resolve(proPath,'src/pages.json')))
      let outData= 'user'
      if(data.globalStyle && data.globalStyle.pageOrientation){

        outData = data.globalStyle.pageOrientation
      }
      console.log('屏幕方向',outData)
      resolve(outData)
    }catch(err){
      reject('获取应用方向失败')
    }
  });
}



function tempTofile(projectName,manifestFile,projectData,sdkDir){
  return new Promise(async (resFn,rejFn)=>{
    try{
      // 权限 
      let permission = await getPermission(manifestFile)
      // 应用图标 路径
      let logPath = await getLogo(manifestFile)
      let app_logo = app_logo2 = path.resolve(proPath  ,logPath)
      // 启动图 路径
      let app_start_img = await getSplashscreen(manifestFile)
      if(app_start_img.indexOf('unpackage') != -1){
        app_start_img = path.resolve(proPath  ,app_start_img)
      }
      // jks 路径 
      let jks = path.resolve( __dirname, '../../public/uploadfile', projectName,projectData.keystore)
      // 获取内核
      let abiFilters = manifestFile['app-plus'].distribute.android.abiFilters || ['armeabi-v7a']
      let pageOrientation = await getPageOrientation(projectName)
      // 获取模块
      let modulesSdk = await androidAddMode({ projectName },manifestFile,projectData)
      console.log('获取模块结束',modulesSdk)
      // 应用版本
      const {versionName,versionCode,name,appid} = manifestFile

      // 是否有自定义插件
      let userPlugins = fs.existsSync(path.resolve(proPath,'dcloud_uniplugins.json'))

      let templateData = {...projectData,jks,pageOrientation,versionName,versionCode,permission,name,app_logo,userPlugins,app_logo2,app_start_img,appid,abiFilters,...modulesSdk}
      console.log('templateData',templateData)
      templates = android(templateData)

      console.log('开始创建文件')
      createConfig(templateData,projectName,sdkDir).then(resFn).catch(rejFn)
    }catch(err){
      console.log(err)
      rejFn(err)
    }
  })
}
// 等待时间
function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms))
}
function createConfig(templateData,projectName,sdkDir){
  return new Promise(async (resFn,rejFn)=>{
    let len = 0
    for (const key in createObj) {
      let obj = createObj[key]
      let pathOut = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS',obj.path)
      switch (obj.type) {
        case 'file':
          createFile(pathOut,key,projectName).then(()=>{
            len++
          }).catch(rejFn)
          break;
        case 'img':
          console.log('开始创建'+key+'图片')
          if(key == 'app_start_img' && !templateData[key]){
            len++
            console.log(key+'使用默认启动图')
            addLog(key+'使用默认启动图',projectName)
          }else{
            copySdk(templateData[key],pathOut).then(()=>{ 
              len++
              console.log(key+'图片创建成功')
              addLog(key+'图片创建成功',projectName)
            }).catch(()=>{
              console.log(key+'图片创建失败')
              addLog(key+'图片创建失败',projectName)
              rejFn()
            })
          }
          break;
        case 'jks':
          console.log('开始复制'+key+'签名文件',templateData[key],pathOut+templateData.keystore)
          copySdk(templateData[key],pathOut+pathType+'keys.keystore').then(()=>{
            len++
            console.log(key+'签名文件复制成功')
            addLog(key+'签名文件复制成功',projectName)
          }).catch(()=>{
            console.log(key+'签名文件复制失败')
            addLog(key+'签名文件复制失败',projectName)
            rejFn()
          })
          break;
      }
    }
    while(len < Object.keys(createObj).length){
      await sleep(100)
    }
    resFn()
  })
}



function createFile(path,key,projectName){
  addLog(`开始生成${key}文件`,projectName)
  console.log(`开始生成${key}文件`)
  return new Promise((resFn,rejFn)=>{
    // 保存template[key]的内容到path
    fs.writeFile(path, templates[key], 'utf8', function(err){
      if(err){
        addLog(`生成${key}失败`,projectName)
        console.log(err)
        rejFn(err)
      }else{
        addLog(`生成${key}成功`,projectName)
        console.log(key+'文件创建成功')
        resFn()
      }
    })
  })

}


module.exports = {
  androidChangeFile,
  androidSign,
  outAndroid
};
